package net.sansi.v3correctserver.task;

import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import net.sansi.v3correctserver.config.matrixloader.DoubleArrMatrixFileLoader;
import net.sansi.v3correctserver.constenum.AppHelper;
import net.sansi.v3correctserver.entity.image.RecCmmImage;
import net.sansi.v3correctserver.entity.screen.CorrectArea;
import net.sansi.v3correctserver.entity.space.CorrectCnf;
import net.sansi.v3correctserver.service.correct.BrightCorrectService;
import net.sansi.v3correctserver.service.correct.areamerge.RecAreaMerge;
import net.sansi.v3correctserver.service.space.ProjectSpace;
import net.sansi.v3correctserver.util.CorrectUtil;
import net.sansi.v3correctserver.util.Matrix;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Fang
 * create time : 2024/11/11
 * IDE : IntelliJ IDEA
 * <p>
 * 区域融合任务
 */
@Slf4j
public class AreaMergeTask extends V3Task<AreaMergeTask, AreaMergeTask.Progress> {

    public static final int TARGET_AUTO = 0;
    public static final int TARGET_BRIGHT = 1;
    public static final int TARGET_CHROMA = 2;

    private final int target;

    private final ProjectSpace projectSpace;
    private final CorrectCnf correctCnf;
    private final BrightCorrectService brightCorrectService;


    public AreaMergeTask(int target) {
        super(5, new Progress());
        this.target = target;
        projectSpace = AppHelper.projectSpace();
        correctCnf = projectSpace.getCorrectCnf();
        brightCorrectService = SpringUtil.getBean(BrightCorrectService.class);
    }

    @Override
    void runHandler() {
        log.info("区域融合开始");
        List<RecAreaMerge.Area> areas = loadCorrectResultAreas();
        log.info("找到 {} 个区域", areas.size());
        RecAreaMerge.Params params = new RecAreaMerge.Params();
        params.areas = areas;
        RecAreaMerge recAreaMerge = new RecAreaMerge(params);
        recAreaMerge.toMerge();
        saveResult(areas);
    }

    /**
     * 保存区域结果
     *
     * @param areas 区域结果
     */
    private void saveResult(List<RecAreaMerge.Area> areas) {

        int w = correctCnf.getScreenWidth(), h = correctCnf.getScreenHeight();
        Matrix<double[]> result = new Matrix<>(w, h, (x, y) -> new double[]{1, 1, 1});

        for (int i = 0; i < 3; i++) {
            Matrix<double[]> merge = saveResultColor(areas, i);
            merge.foreach((x, y, item) -> {
                addDoubleResult(item, result.get(x, y));
            });
        }

        result.setLoader(new DoubleArrMatrixFileLoader(3));
        result.save(projectSpace.brightMergeResult(3, correctCnf.getFixLine()));

        RecCmmImage show = CorrectUtil.result2Preview(result, correctCnf.getCameraParams().get(0).getBrightness());
        show.save(projectSpace.brightMergeShow(3, correctCnf.getFixLine()));
    }

    /**
     * 保存单个颜色的结果
     *
     * @param areas    区域结果
     * @param colorIdx 颜色索引
     * @return 结果
     */
    private Matrix<double[]> saveResultColor(List<RecAreaMerge.Area> areas, int colorIdx) {

        int w = correctCnf.getScreenWidth(), h = correctCnf.getScreenHeight();
        Matrix<double[]> colorRes = new Matrix<>(w, h, (x, y) -> new double[]{1, 1, 1});

        for (RecAreaMerge.Area area : areas) {
            Matrix<double[]> result = area.getResult(colorIdx);
            area.foreachValidInShowArea((sx, sy, rx, ry) -> {
                colorRes.set(sx, sy, result.get(rx, ry));
            });
        }

        colorRes.setLoader(new DoubleArrMatrixFileLoader(3));
        colorRes.save(projectSpace.brightMergeResult(colorIdx, correctCnf.getFixLine()));

        RecCmmImage show = CorrectUtil.result2Preview(colorRes, correctCnf.getCameraParams().get(0).getBrightness());
        show.save(projectSpace.brightMergeShow(colorIdx, correctCnf.getFixLine()));

        return colorRes;
    }

    /**
     * 累加 结果
     *
     * @param source 原始
     * @param target 目标
     */
    private void addDoubleResult(double[] source, double[] target) {
        for (int i = 0; i < 3; i++) {
            target[i] += source[i] == 0 ? 0 : source[i] - 1;
        }
    }

    /**
     * 加载矫正结果区域
     *
     * @return 区域列表
     */
    private List<RecAreaMerge.Area> loadCorrectResultAreas() {
        List<RecAreaMerge.Area> res = new ArrayList<>();
        for (CorrectArea area : correctCnf.getAreas()) {
            RecAreaMerge.Area a = null;
            if (TARGET_AUTO == target) {
                a = loadChromaResult(area);
                if (a == null) a = loadBrightResult(area);
            } else if (TARGET_BRIGHT == target) {
                a = loadBrightResult(area);
            } else if (TARGET_CHROMA == target) {
                a = loadChromaResult(area);
            }
            if (a != null) res.add(a);
        }
        return res;
    }

    /**
     * 加载亮度结果
     *
     * @param area 区域
     * @return 区域
     */
    private RecAreaMerge.Area loadBrightResult(CorrectArea area) {

        List<Matrix<Double>> brightResults = brightCorrectService.loadCorrectResult(area);
        List<Matrix<double[]>> results = new ArrayList<>();
        RecAreaMerge.Area res = RecAreaMerge.Area.of(area);

        for (int i = 0; i < 3; i++) {
            results.add(CorrectUtil.brightResult2ChromaResult(brightResults.get(i), i));
        }

        res.setResults(results);

        return res;
    }

    /**
     * 加载色度结果
     *
     * @param area 区域
     * @return 区域
     */
    private RecAreaMerge.Area loadChromaResult(CorrectArea area) {
        return null;
    }

    public static class Progress extends V3Task.Progress {
    }
}
